﻿
using Microsoft.Extensions.DependencyInjection;

using MTP.Core.Filters;

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Sockets;

namespace MTP.Core
{
    public class MtpOptions
    {
        public MtpOptions()
        {
            Filters = new FilterMtpCollection();
            MtpUrl = "mtp://localhost:*/";
            Services = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
            RemoteServices = new List<RemoteOptions>();
        }

        /// <summary>
        /// 本地密钥
        /// </summary>
        private string GetCipher(string mtpUrl)
        {
            if (string.IsNullOrEmpty(mtpUrl))
            {
                throw new ArgumentNullException("mtpUrl");
            }
            var index = mtpUrl.IndexOf("//") + 2;
            var mtp = mtpUrl.Substring(index);
            var nextIndex = mtp.IndexOf("/") + 1;
            if (nextIndex <= 0)
            {
                return Guid.NewGuid().ToString("N").Substring(0, 8);
            }
            var next = mtp.Substring(nextIndex);
            if (string.IsNullOrEmpty(next))
            {
                return Guid.NewGuid().ToString("N").Substring(0, 8);
            }
            return next;
        }

        private void SetMtp(string mtpUrl)
        {

            if (!MTPCoreUtil.TryParseMtpUrl(mtpUrl, out int port, out string hostname))
            {
                throw new FormatException("MtpOptions:MtpUrl");
            }
            Port = port;
            HostName = hostname;
            Cipher = GetCipher(mtpUrl);
        }

        public string MtpUrl
        {
            get { return $"mtp://{HostName}:{Port}/{Cipher}"; }
            set { SetMtp(value); }
        }

        public string Cipher { get; set; }

        public string HostName { get; set; }

        public int Port { get; set; }

        public Func<IServiceProvider, IMTPRegistry> Registry { get; set; }


        public MtpOptions UseServiceFactory(Action<Func<IServiceProvider, Type, object[], object>> action)
        {
            action?.Invoke(MtpRemoteFactory.CreateInstance);
            return this;
        }
        /// <summary>
        /// 过滤器
        /// </summary>
        public FilterMtpCollection Filters { get; }

        internal List<RemoteOptions> RemoteServices { get; set; }

        public void AddRemoteServices(IEnumerable<RemoteOptions> optionss)
        {
            RemoteServices.Clear();
            RemoteServices.AddRange(optionss);
        }

        /// <summary>
        /// 本地服务
        /// </summary>
        internal IDictionary<string, Type> Services { get; }

        internal void AddRangeServices(ICollection<Type> types)
        {
            foreach (var type in types)
            {
                Services.Add(type.Name, type);
            }
        }
    }
}
